package com.raising.framework.filter;

import com.raising.framework.filter.realm.MyUsernamePasswordToken;
import com.raising.utils.JCacheUtils;
import com.raising.utils.JStringUtils;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

/**
 * 自定义表单登录验证
 * @author gaoy
 * 2017 2017-5-7 下午7:24:35
 */
public class MyFormAuthenticationFilter extends FormAuthenticationFilter{
    public static final String DEFAULT_TYPE_PARAM = "type";
    private String typeParam = DEFAULT_TYPE_PARAM;
    public static final String DEFAULT_VALIDATECODE_PARAM = "validateCode";
    private String validateCodeParam = DEFAULT_VALIDATECODE_PARAM;
    public static final String DEFAULT_JUMPURL_PARAM = "jumpUrl";
    private String jumpUrlParam = DEFAULT_JUMPURL_PARAM;

	
	protected String getType(ServletRequest request) {
        return WebUtils.getCleanParam(request, getTypeParam());
    }
    protected String getValidateCode(ServletRequest request) {
        return WebUtils.getCleanParam(request, getValidateCodeParam());
    }
    protected String getJumpUrl(ServletRequest request) {
        return WebUtils.getCleanParam(request, getJumpUrlParam());
    }

    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {
        String username = getUsername(request);
        String password = getPassword(request);
        String type = getType(request);
        String validateCode = getValidateCode(request);
        String jumpUrl = getJumpUrl(request);
        return createToken(username, password,type,validateCode,jumpUrl, request, response);
    }
	
	protected AuthenticationToken createToken(String username, String password,String type,String validateCode,String jumpUrl,
              ServletRequest request, ServletResponse response) {
		boolean rememberMe = isRememberMe(request);
		String host = getHost(request);
		return createToken(username, password,type,validateCode,jumpUrl, rememberMe, host);
	}
	
	protected AuthenticationToken createToken(String username, String password,String type,String validateCode,String jumpUrl,
             boolean rememberMe, String host) {
		return new MyUsernamePasswordToken(username, password,type,validateCode,jumpUrl, rememberMe, host);
	}
	
	/**
     * 校验验证码
     * @author gaoy
     * 原FormAuthenticationFilter的认证方法
     * 该方法会在realm前调用 
     * 由于验证码是我们自己生成存在session里的，所以我们需要在登录时判断验证码是否成功就可用该方法
     * 
     * 验证码为空或验证成功 继续执行父类的onAccessDenied方法
     * 验证码不为空且验证失败，返回true则不再走realm,直接进控制器的login.do
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response, Object map) throws Exception {
    	 // 从cache获取正确的验证码
         String validateCode = (String) JCacheUtils.get("validateCode");
         String inputCode = getValidateCode(request);
//        //页面输入的验证码
//        String randomcode = request.getParameter("checkCode");

        //判断验证码
        if(inputCode==null||!inputCode.equals(validateCode)){
            //如果校验失败，将验证码错误失败信息，通过shiroLoginFailure设置到request中
            request.setAttribute("shiroLoginFailure", "randomCodeError");
            //拒绝访问，不再校验账号和密码
            return true;
        }

        return super.onAccessDenied(request, response, map);


    }
    /**
     *  @describe: 解决重新登录不能挤出当前登录用户的问题
     *  @author: GaoYuan
     *  @create_date: 2017/9/30 上午10:16
     *  @param:
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
    {
        if (isLoginRequest(request, response))
        {
            if (isLoginSubmission(request, response))
            {
                //本次用户登陆账号
                String account = this.getUsername(request);
                Subject subject = this.getSubject(request, response);
                //之前登陆的用户
                String userName = (String)  subject.getPrincipal();
                //如果两次登陆的用户不一样，则先退出之前登陆的用户
                if (account != null && !account.equals(userName))
                {
                    subject.logout();
                }
            }
        }

        return super.isAccessAllowed(request, response, mappedValue);
    }
    /**
     *  登录成功后会触发此方法
     *  @describe: 自定义跳转路径
     *  @author: GaoYuan
     *  @create_date: 2017/9/30 上午10:27
     *  @param:
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject,
                                     ServletRequest request, ServletResponse response) throws Exception {
//        issueSuccessRedirect(request, response);
        //获取跳转的路径
        HttpServletRequest re = (HttpServletRequest)request;
        String jumpUrl = re.getParameter("jumpUrl");
        WebUtils.getAndClearSavedRequest(request);
        if(JStringUtils.isNotBlank(jumpUrl)){
            WebUtils.redirectToSavedRequest(request,response,"/check?jumpUrl="+jumpUrl);
            return false;
        }
        WebUtils.redirectToSavedRequest(request,response,"/check");
        return false;
    }



    public String getTypeParam() {
        return typeParam;
    }

    public void setTypeParam(String typeParam) {
        this.typeParam = typeParam;
    }

    public String getValidateCodeParam() {
        return validateCodeParam;
    }

    public void setValidateCodeParam(String validateCodeParam) {
        this.validateCodeParam = validateCodeParam;
    }

    public String getJumpUrlParam() {
        return jumpUrlParam;
    }

    public void setJumpUrlParam(String jumpUrlParam) {
        this.jumpUrlParam = jumpUrlParam;
    }

}